import excepts
import binascii

"""
   This module parses MXF files.
   Does not use the BinaryStream class from libmxit
"""

# ATTRIBUTION: http://www.python-forum.org/pythonforum/viewtopic.php?f=2&t=6450
def dec2bin(n):
   s = ''
   while n:
      s = str(n % 2) + s
      n = n / 2
   return s


class mxfReader:
   types = {
      '6f': 'FrameImageDesc'
   };

   fieldTypes = {
      '0c': 'name',
      '81': 'shortcut',
      '82': 'data',
      '83': 'frameCountW',
      '84': 'frameCountH',
      '85': 'time'
   };

   def __init__(self,data):
      self.data = data;
      
      # Do a check on the data
      if not data.startswith("MXF"):
         raise excepts.MalformedMXFData;
         return;
      
   # We have to see what type of MXF this is
   def parse(self):
      type = binascii.hexlify(self.data[4:5]);
      try:
         fName = self.types[type];
      except KeyError:
         raise excepts.UnsupportedMXFType;
         return;
      
      func = getattr(self,'parse' + fName);
      length = self.parseLength(self.data[5:]);
      
      return func(length[0],self.data[5+length[1]:]);

   
   def parseLength(self,data):
      fByte = binascii.hexlify(data[0]); # First byte

      if int(fByte,16) in range(0,9):
         length = int(fByte,16);
         bytes = 0;
      else:
         binString = dec2bin(int(fByte,16)); # Turn it into a binary string (eg: 10000010)
         binString = "0" + binString[1:];
         bytes = int(binString,2);
      
         # Get length from next bytes
         hexLength = binascii.hexlify(data[1:bytes+1]);
         length = int(hexLength,16);
      
      return (length,bytes+1);


   def parseFrameImageDesc(self,length,data):
      mxfObject = mxf();
      
      i = 0;
      while i < length:
         try:
            fieldName = self.fieldTypes[binascii.hexlify(data[i])];
            (fieldLength,skip) = self.parseLength(data[i+1:]);
            fieldValue = data[i+1+skip:i+1+skip+fieldLength];
            setattr(mxfObject,fieldName,fieldValue);
         except (KeyError,IndexError):
            name = binascii.hexlify(data[i]);
            value = data[i+1+skip:i+1+skip+fieldLength];
            #print "Error: Unsupported fieldType %s for data %s" % (name,binascii.hexlify(value));
        
         i = i+1+skip+fieldLength;

      # the MXF object is complete!
      return mxfObject;


# An MXF object. It doesn't do much, really.
class mxf:
   name = None;
   data = None;

   def __init__(self):
      pass;